﻿/*
 源码己托管:http://git.oschina.net/kuiyu/dotnetcodes
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Dora.Tools.Enums.Contract;
using Dora.Tools.Enums.Customers;
using Dora.Tools.Enums.Order;
using Dora.Tools.Enums.Product;
using Newtonsoft.Json;

namespace Dora.Tools.Utility
{
    /// <summary>
    /// 处理数据类型转换，数制转换、编码转换相关的类
    /// </summary>    
    public sealed class ConvertHelper
    {
        #region 补足位数
        /// <summary>
        /// 指定字符串的固定长度，如果字符串小于固定长度，
        /// 则在字符串的前面补足零，可设置的固定长度最大为9位
        /// </summary>
        /// <param name="text">原始字符串</param>
        /// <param name="limitedLength">字符串的固定长度</param>
        public static string RepairZero(string text, int limitedLength)
        {
            //补足0的字符串
            string temp = "";

            //补足0
            for (int i = 0; i < limitedLength - text.Length; i++)
            {
                temp += "0";
            }

            //连接text
            temp += text;

            //返回补足0的字符串
            return temp;
        }
        #endregion

        #region 各进制数间转换
        /// <summary>
        /// 实现各进制数间的转换。ConvertBase("15",10,16)表示将十进制数15转换为16进制的数。
        /// </summary>
        /// <param name="value">要转换的值,即原值</param>
        /// <param name="from">原值的进制,只能是2,8,10,16四个值。</param>
        /// <param name="to">要转换到的目标进制，只能是2,8,10,16四个值。</param>
        public static string ConvertBase(string value, int from, int to)
        {
            try
            {
                int intValue = Convert.ToInt32(value, from);  //先转成10进制
                string result = Convert.ToString(intValue, to);  //再转成目标进制
                if (to == 2)
                {
                    int resultLength = result.Length;  //获取二进制的长度
                    switch (resultLength)
                    {
                        case 7:
                            result = "0" + result;
                            break;
                        case 6:
                            result = "00" + result;
                            break;
                        case 5:
                            result = "000" + result;
                            break;
                        case 4:
                            result = "0000" + result;
                            break;
                        case 3:
                            result = "00000" + result;
                            break;
                    }
                }
                return result;
            }
            catch
            {

                //LogHelper.WriteTraceLog(TraceLogLevel.Error, ex.Message);
                return "0";
            }
        }
        #endregion

        #region 使用指定字符集将string转换成byte[]
        /// <summary>
        /// 使用指定字符集将string转换成byte[]
        /// </summary>
        /// <param name="text">要转换的字符串</param>
        /// <param name="encoding">字符编码</param>
        public static byte[] StringToBytes(string text, Encoding encoding)
        {
            return encoding.GetBytes(text);
        }
        #endregion

        #region 使用指定字符集将byte[]转换成string
        /// <summary>
        /// 使用指定字符集将byte[]转换成string
        /// </summary>
        /// <param name="bytes">要转换的字节数组</param>
        /// <param name="encoding">字符编码</param>
        public static string BytesToString(byte[] bytes, Encoding encoding)
        {
            return encoding.GetString(bytes);
        }
        #endregion

        #region 将byte[]转换成int
        /// <summary>
        /// 将byte[]转换成int
        /// </summary>
        /// <param name="data">需要转换成整数的byte数组</param>
        public static int BytesToInt32(byte[] data)
        {
            //如果传入的字节数组长度小于4,则返回0
            if (data.Length < 4)
            {
                return 0;
            }

            //定义要返回的整数
            int num = 0;

            //如果传入的字节数组长度大于4,需要进行处理
            if (data.Length >= 4)
            {
                //创建一个临时缓冲区
                byte[] tempBuffer = new byte[4];

                //将传入的字节数组的前4个字节复制到临时缓冲区
                Buffer.BlockCopy(data, 0, tempBuffer, 0, 4);

                //将临时缓冲区的值转换成整数，并赋给num
                num = BitConverter.ToInt32(tempBuffer, 0);
            }

            //返回整数
            return num;
        }
        #endregion

        #region unix时间戳转换
        /// <summary>  
        /// 获取时间戳  13位
        /// </summary>  
        /// <returns></returns>  
        public static long GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds * 1000);
        }

        /// <summary> 
        /// 获取时间戳  10位
        /// </summary> 
        /// <returns></returns> 
        public static string GetTimeStampLength10()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// 将时间戳转换为日期类型，并格式化
        /// </summary>
        /// <param name="longDateTime"></param>
        /// <returns></returns>
        public static string LongDateTimeToDateTimeString(string longDateTime)
        {
            ////用来格式化long类型时间的,声明的变量
            //long unixDate;
            //DateTime start;
            //DateTime date;
            ////ENd

            //unixDate = long.Parse(longDateTime);
            //start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            //date = start.AddMilliseconds(unixDate).ToLocalTime();

            //return date.ToString("yyyy-MM-dd HH:mm:ss");
            if (string.IsNullOrEmpty(longDateTime))
            {
                return "";
            }
            long unixDate = 0;
            long.TryParse(longDateTime, out unixDate);
            var date = LongToDateTime(unixDate);
            if (date.HasValue)
            {
                return date.Value.ToString("yyyy-MM-dd HH:mm:ss");
            }
            return "";

        }
        /// <summary>
        /// 将时间戳转换为日期类型
        /// </summary>
        /// <param name="longDateTime"></param>
        /// <returns></returns>
        public static DateTime? LongToDateTime(long? longDateTime)
        {
            if (longDateTime == null || longDateTime == 0)
            {
                return null;
            }
            //用来格式化long类型时间的,声明的变量
            long unixDate;
            DateTime start;
            DateTime date;
            //ENd

            unixDate = longDateTime.Value;// long.Parse(longDateTime);
            start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            date = start.AddMilliseconds(unixDate).ToLocalTime();

            return date;

        }
        /// <summary>
        /// 将时间戳转换为日期类型，并格式化
        /// </summary>
        /// <param name="longDateTime"></param>
        /// <returns></returns>
        public static DateTime? StrLongToDateTime(string longDateTime)
        {
            if (string.IsNullOrEmpty(longDateTime))
            {
                return null;
            }
            long unixDate = 0;
            long.TryParse(longDateTime, out unixDate);
            var date = LongToDateTime(unixDate);
            return date;
        }
        #endregion

        #region base64
        /// <summary>
        /// base64
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConverBase64String(string str)
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(str));
        }

        #endregion

        #region H256签名方法
        /// <summary>
        /// H256签名方法
        /// </summary>
        /// <param name="message"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string HMACSHA256(string message, string secret)
        {
            secret = secret ?? "";
            byte[] keyByte = Encoding.UTF8.GetBytes(secret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashmessage);
            }
        }
        #endregion

        #region Ascii排序
        /// <summary>
        /// Ascii排序
        /// </summary>
        /// <param name="sArray"></param>
        /// <returns></returns>
        public static Dictionary<string, string> AsciiDictionary(Dictionary<string, string> sArray)
        {
            Dictionary<string, string> asciiDic = new Dictionary<string, string>();
            string[] arrKeys = sArray.Keys.ToArray();
            Array.Sort(arrKeys, string.CompareOrdinal);
            foreach (var key in arrKeys)
            {
                string value = sArray[key];
                asciiDic.Add(key, value);
            }
            return asciiDic;
        }

        #endregion

        #region 项目专用
        /// <summary>
        /// string按字符返回数组
        /// </summary>
        /// <param name="text">要转换的字符串</param>
        /// <param name="encoding">字符编码</param>
        public static List<T> StringToList<T>(string text, char splitChar)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return new List<T>();
            }
            var arr = text.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);
            var list=new List<T>();
            if (typeof(T) == typeof(string))
            {
                return list;
            }
            else if(typeof(T).IsValueType)
            {
                foreach (var item in arr)
                {
                    var newItem = (T)Convert.ChangeType(item, typeof(T));
                    list.Add(newItem);
                }
            }
            
            return list;
        }
        /// <summary>
        /// 从环信用户名获取系统Id
        /// </summary>
        /// <param name="hxUserName"></param>
        /// <returns></returns>
        public static int GetSystemIdFromHxUserName(string hxUserName)
        {
            int systemId = 0;
            var userId = Guid.Empty;
            if (string.IsNullOrWhiteSpace(hxUserName))
            {
                return systemId;
            }

            var arrTo = hxUserName.Split('_');
            if (arrTo.Length == 2)
            {
                int.TryParse(arrTo[0], out systemId);
                Guid.TryParse(arrTo[1], out userId);
            }

            return systemId;
        }
        /// <summary>
        /// 从环信用户名获取用户Id
        /// </summary>
        /// <param name="hxUserName"></param>
        /// <returns></returns>
        public static Guid GetUserIdFromHxUserName(string hxUserName)
        {
            int systemId = 0;
            //int orgId = 0;
            var userId = Guid.Empty;
            if (string.IsNullOrWhiteSpace(hxUserName))
            {
                return userId;
            }

            var arrTo = hxUserName.Split('_');
            if (arrTo.Length >= 2)
            {
                int.TryParse(arrTo[0], out systemId);
                Guid.TryParse(arrTo[1], out userId);
            }

            return userId;
        }
        /// <summary>
        /// 随即生成产品编号
        /// </summary>
        /// <returns></returns>
        public static string GenerateProductCode()
        {
            var result = new StringBuilder();
            for (var i = 0; i < 10; i++)
            {
                var r = new Random(Guid.NewGuid().GetHashCode());
                result.Append(r.Next(0, 10));
            }
            return result.ToString();
        }

        /// <summary>
        /// 根据身份证号获取出生日期
        /// </summary>
        /// <returns></returns>
        public static DateTime? GetBirthdayFromIdCard(string Id)
        {
            if (!string.IsNullOrEmpty(IdChecker.ChekcId(Id)))
            {
                return null;
            }

            string birth = "";
            DateTime birthTime = new DateTime();
            if (Id.Length == 18)
            {
                birth = Id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            }
            else if (Id.Length == 15)
            {
                birth = Id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            }
            else
            {
                return null;
            }

            if (DateTime.TryParse(birth, out birthTime) == false)
            {
                return null;//生日验证
            }

            return birthTime;
        }

        /// <summary>
        /// 根据身份证号判断客户类型
        /// </summary>
        /// <returns></returns>
        /// <remarks>出生日期和出团日期做对比，出生日期小于出团日期为成人，出生日期大于或等于出团日期为儿童</remarks>
        public static CustomerCType? GetCustomerTypeFromIdCard(string Id,DateTime startDate)
        {
            if (!string.IsNullOrEmpty(IdChecker.ChekcId(Id)))
            {
                return null;
            }

            string birth = "";
            DateTime birthTime = new DateTime();
            if (Id.Length == 18)
            {
                birth = Id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            }
            else if (Id.Length == 15)
            {
                birth = Id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            }
            else
            {
                return null;
            }

            if (DateTime.TryParse(birth, out birthTime) == false)
            {
                return null;//生日验证
            }

            if (startDate < birthTime)
            {
                return null;
            }

            var childDate = startDate.AddYears(-12);
            if (birthTime <= childDate)
            {
                return CustomerCType.Adult;
            }
            else
            {
                return CustomerCType.Child;
            }
        }


        /// <summary>
        /// 根据出生日期判断客户类型
        /// </summary>
        /// <returns></returns>
        /// <remarks>出生日期和出团日期做对比，出生日期小于出团日期为成人，出生日期大于或等于出团日期为儿童</remarks>
        public static CustomerCType? GetCustomerTypeFromBirthday(DateTime? birthday, DateTime startDate)
        {
            if (!birthday.HasValue)
            {
                return null;
            }

            DateTime birthTime = birthday.Value;

            if (startDate < birthTime)
            {
                return null;
            }

            var childDate = startDate.AddYears(-12);
            if (birthTime >= childDate)
            {
                return CustomerCType.Child;
            }
            else
            {
                return CustomerCType.Adult;
            }
        }


        /// <summary>
        /// 获取显示的名字
        /// </summary>
        /// <returns></returns>
        public static string GetShowName(string firstName,string secondName)
        {
            var showName = "";
            if (!string.IsNullOrWhiteSpace(firstName))
            {
                showName = firstName;
            }
            else
            {
                showName = secondName;
            }
            return showName;
        }

        /// <summary>
        /// 获取全名
        /// </summary>
        /// <returns></returns>
        public static string GetFullName(string cnName, string enName)
        {
            var showName = "";
            if (!string.IsNullOrWhiteSpace(cnName))
            {
                showName = cnName;
            }
            else
            {
                showName = enName;
            }
            return showName;
        }

        public static OrderStatusOne GetOrderStatusOne(int? OrderState, int? RefundState, int? PayState, int? SetOutState,DateTime? DepartureDate,DateTime? GoBackDate)
        {
            OrderStatusOne state = OrderStatusOne.None;
            if (OrderState == (int)OrderStatus.PendingConfirm)
            {
                state = OrderStatusOne.BeConfirmed;
            }
            else if (OrderState == (int)OrderStatus.Cancelled)
            {
                state = OrderStatusOne.Canceled;
            }
            else if (RefundState != (int)RefundStatus.None && RefundState != (int)RefundStatus.RejectRefund && RefundState != (int)RefundStatus.RefundToTourist)
            {
                state = OrderStatusOne.Refunding;
            }
            else if (RefundState == (int)RefundStatus.RefundToTourist)
            {
                state = OrderStatusOne.Refunded;
            }
            else if (PayState == (int)PaymentStatus.Pending || PayState == (int)PaymentStatus.Paying)
            {
                state = OrderStatusOne.BePaid;
            }
            else if (SetOutState == (int)SetOutStatus.Pending)
            {
                state = OrderStatusOne.BeTravelled;
            }
            else if (SetOutState == (int)SetOutStatus.Traveling || (DepartureDate < DateTime.Now && GoBackDate > DateTime.Now))
            {
                state = OrderStatusOne.Travelling;
            }
            else if (SetOutState == (int)SetOutStatus.Returned || GoBackDate < DateTime.Now)
            {
                state = OrderStatusOne.Completed;
            }
            return state;
        }
               
        /// <summary>
        /// 从组织机构LevelPath中获取ParentId
        /// </summary>
        /// <returns></returns>
        public static int OrgGetParentIdFromLevelPath(string levelPath)
        {
            var parentOrgIdArr = levelPath.Split(',', StringSplitOptions.RemoveEmptyEntries);
            if (parentOrgIdArr.Length < 2)
            {
                return 0;
            }
            var parentOrgId = parentOrgIdArr[parentOrgIdArr.Length - 2];
            return int.Parse(parentOrgId);
        }

        /// <summary>
        /// 从组织机构LevelPath中获取TopOrgId
        /// </summary>
        /// <returns></returns>
        public static int OrgGetTopIdFromLevelPath(string levelPath)
        {
            var parentOrgIdArr = levelPath.Split(',', StringSplitOptions.RemoveEmptyEntries);
            if (parentOrgIdArr.Length < 1)
            {
                return 0;
            }
            var parentOrgId = parentOrgIdArr[0];
            return int.Parse(parentOrgId);
        }


        /// <summary>
        /// 根据产品类型 目的地 是否单项委托 判断何种产品模板
        /// </summary>
        /// <returns></returns>
        public static TemplateTypeEnum GetContractTemplateId(int productTypeId1, int productTypeId2,string toProvinceName,short? touristType)
        {
            TemplateTypeEnum TemplateId = TemplateTypeEnum.A00001;
            if (productTypeId1 == (int)ProductType.YouLun && productTypeId2 == 64)// //境内合同：境内游产品，邮轮游国内产品；
            {
                TemplateId = TemplateTypeEnum.A00001;
            }
            if (productTypeId1 == (int)ProductType.GuoNeiYou)// //境内合同：境内游产品，邮轮游国内产品；
            {
                TemplateId = TemplateTypeEnum.A00001;
            }
            //出境合同：海外长线，海外短线，邮轮游出境产品；
            if (productTypeId1 == (int)ProductType.HaiChang || productTypeId1 == (int)ProductType.HaiDuan || (productTypeId1 == (int)ProductType.YouLun && productTypeId2 == 65))
            {
                TemplateId = TemplateTypeEnum.C00001;
            }
            if (productTypeId1 == (int)ProductType.ZhouBianYou)//一日游合同：周边游产品；
            {
                TemplateId = TemplateTypeEnum.D00001;
            }
            //代订代办：单项委托产品（暂时不提供）
            if (touristType == (int)TouristType.SingleEntrustment)
            {
                TemplateId = TemplateTypeEnum.E00001;
            }
            //赴台合同：目的地“台湾”的产品；
            if (toProvinceName.Trim().Contains("台湾"))
            {
                TemplateId = TemplateTypeEnum.F00001;
            }
            return TemplateId;
        }


        /// <summary>
        /// 计算年龄
        /// </summary>
        /// <param name="birthday"></param>
        /// <param name="compareDate"></param>
        /// <returns></returns>
        public static int GetAge(DateTime birthday, DateTime compareDate)
        {
            int age = compareDate.Year - birthday.Year;
            if (birthday > compareDate.AddYears(-age).AddDays(1)) age--;
            return age;
        }

        #endregion

        #region 护照数据转换
        /// <summary>
        /// 获取护照的生日
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetHZBirthday(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return "";
            }

            var enMonth = StringHelper.GetAlpha(str);
            var numMonth = DateHelper.MonthFromEnAbbrToNum(enMonth);
            if (numMonth == 0)
            {
                return "";
            }

            var strArr = str.Split(enMonth, StringSplitOptions.RemoveEmptyEntries);
            if (strArr.Length < 2)
            {
                return "";
            }
            var numDay = 0;
            var numYear = 0;
            int.TryParse(strArr[0], out numDay);
            int.TryParse(strArr[1], out numYear);
            var birthday = $"{numYear}-{numMonth}-{numDay}";
            return birthday;
        }

        /// <summary>
        /// 获取护照的有效期
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetHZValidThru(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return "";
            }

            var enMonth = StringHelper.GetAlpha(str);
            var numMonth = DateHelper.MonthFromEnAbbrToNum(enMonth);
            if (numMonth == 0)
            {
                return "";
            }

            var strArr = str.Split(enMonth, StringSplitOptions.RemoveEmptyEntries);
            if (strArr.Length < 2)
            {
                return "";
            }
            var numDay = 0;
            var numYear = 0;
            int.TryParse(str.Substring(0,2), out numDay);
            int.TryParse(strArr[1], out numYear);
            var birthday = $"{numYear}-{numMonth}-{numDay}";
            return birthday;
        }

        /// <summary>
        /// 获取护照的性别 男 女
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetHZSex(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return "";
            }
            if (str.StartsWith("男"))
            {
                return "男";
            }
            else if (str.StartsWith("女"))
            {
                return "女";
            }
            else
            {
                return "";
            }
        }
        #endregion

        #region GUID转换

        /// <summary>
        /// 根据GUID获取16位的唯一字符串
        /// </summary>
        /// <param name=\"guid\"></param>
        /// <returns></returns>
        public static string GuidTo16String(Guid guid)
        {
            long i = 1;
            foreach (byte b in guid.ToByteArray())
                i *= ((int)b + 1);
            return string.Format("{0:x}", i - DateTime.Now.Ticks);
        }
        /// <summary>
        /// 根据GUID获取19位的唯一数字序列
        /// </summary>
        /// <returns></returns>
        public static long GuidToLongID(Guid guid)
        {
            byte[] buffer = guid.ToByteArray();
            return BitConverter.ToInt64(buffer, 0);
        }

        #endregion

        #region 产品收客年龄限制转换
        /// <summary>
        /// 判断超出年龄限制的生日数量
        /// </summary>
        /// <param name="errPre">错误提示前缀</param>
        /// <returns>空字符串表示符合条件，否则不符合条件</returns>
        public static int AgeLimitIsInList(SortedList<int, int> ageList, List<DateTime> birthdayList, DateTime selectDate)
        {
            if (birthdayList == null || birthdayList.Count == 0)
            {
                return 0;
            }
            if (ageList == null || ageList.Count ==0)
            {
                return birthdayList.Count;
            }

            //var childDate = DateTime.Now.AddYears(-12);
            //if (birthTime >= childDate)
            //{
            //    return CustomerCType.Child;
            //}
            //else
            //{
            //    return CustomerCType.Adult;
            //}
            int outNum = 0;
            foreach (var birthDay in birthdayList)
            {
                int age = GetAge(birthDay, selectDate);
                var isIn = false;
                foreach (var itemArea in ageList)
                {
                    if (itemArea.Key <= age && age <= itemArea.Value)
                    {
                        isIn = true;
                    }
                }
                if (isIn==false)
                {
                    outNum++;
                }
            }
            return outNum;
        }

        /// <summary>
        /// 年龄List检查
        /// </summary>
        /// <param name="errPre">错误提示前缀</param>
        /// <returns>空字符串表示符合条件，否则不符合条件</returns>
        public static string AgeLimitListCheck(SortedList<int, int> list, string errPre)
        {
            if (list == null || list.Count == 0)
            {
                return $"请填写至少一个{errPre}限制年龄段";
            }
            if (list == null || list.Count > 5)
            {
                return $"{errPre}限制年龄段不能超过5个";
            }

            var str = AgeLimitListToString(list);
            if (str.Length > 50)
            {
                return $"{errPre}限制年龄数量超长或年龄超长";
            }
            return "";
        }

        /// <summary>
        /// 年龄List转换成形如12:20;30:50;65:100
        /// </summary>
        /// <param name=\"guid\"></param>
        /// <returns></returns>
        public static string AgeLimitListToString(SortedList<int, int> list)
        {
            if (list == null || list.Count == 0)
            {
                return "";
            }

            var str = "";
            foreach (var item in list)
            {
                str += $"{item.Key}:{item.Value};";
            }

            return str;
        }

        /// <summary>
        /// 年龄字符串转换成List
        /// </summary>
        /// <param name=\"guid\"></param>
        /// <returns></returns>
        public static SortedList<int, int> AgeLimitStringToList(string str)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return new SortedList<int, int>();
            }

            var list = new SortedList<int, int>();
            var arr = str.Split(';', StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in arr)
            {
                var arrItem = item.Split(':', StringSplitOptions.RemoveEmptyEntries);
                if (arrItem.Length == 2)
                {
                    list.Add(int.Parse(arrItem[0]), int.Parse(arrItem[1]));
                }
            }

            return list;
        }
        #endregion
    }
}
